// API 错误处理和最佳实践示例

import { ElMessage, ElNotification } from 'element-plus'

// ==================== 1. 统一的错误处理 ====================

/**
 * 统一的 API 错误处理函数
 * @param {Error} error - 错误对象
 * @param {string} operation - 操作描述
 */
export function handleApiError(error, operation = '操作') {
  console.error(`${operation}失败:`, error)
  
  // 根据错误类型显示不同的提示
  if (error.message.includes('HTTP error')) {
    // HTTP 状态码错误
    const status = error.message.match(/status: (\d+)/)?.[1]
    switch (status) {
      case '400':
        ElMessage.error('请求参数错误')
        break
      case '401':
        ElMessage.error('未授权，请重新登录')
        // 可以在这里跳转到登录页
        break
      case '403':
        ElMessage.error('权限不足')
        break
      case '404':
        ElMessage.error('请求的资源不存在')
        break
      case '500':
        ElMessage.error('服务器内部错误')
        break
      default:
        ElMessage.error(`网络错误 (${status})`)
    }
  } else if (error.message.includes('API error')) {
    // 业务逻辑错误
    ElMessage.error(error.message.replace('API error: ', ''))
  } else if (error.message.includes('Failed to fetch')) {
    // 网络连接错误
    ElMessage.error('网络连接失败，请检查网络设置')
  } else {
    // 其他错误
    ElMessage.error(error.message || `${operation}失败`)
  }
}

// ==================== 2. API 请求封装 ====================

/**
 * 通用的 API 请求函数
 * @param {string} url - 请求地址
 * @param {Object} options - 请求选项
 * @param {string} operation - 操作描述（用于错误提示）
 */
export async function apiRequest(url, options = {}, operation = '请求') {
  try {
    // 设置默认选项
    const defaultOptions = {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    }
    
    // 合并选项
    const finalOptions = { ...defaultOptions, ...options }
    
    // 添加认证 token（如果存在）
    const token = localStorage.getItem('admin_token')
    if (token) {
      finalOptions.headers.Authorization = `Bearer ${token}`
    }
    
    console.log(`发送${operation}请求:`, { url, options: finalOptions })
    
    // 发送请求
    const response = await fetch(url, finalOptions)
    
    // 检查 HTTP 状态
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }
    
    // 解析响应
    const result = await response.json()
    
    console.log(`${operation}响应:`, result)
    
    // 检查业务状态码
    if (result.code === 200) {
      return result.data
    } else {
      throw new Error(`API error: ${result.msg || result.message}`)
    }
  } catch (error) {
    handleApiError(error, operation)
    throw error
  }
}

// ==================== 3. 具体的 API 函数示例 ====================

/**
 * 获取店铺列表 - 使用统一封装
 */
export async function getShopListWithErrorHandling(params = {}) {
  return await apiRequest('/api/admin/foodStore/page', {
    method: 'POST',
    body: JSON.stringify(params)
  }, '获取店铺列表')
}

/**
 * 创建店铺 - 带验证的版本
 */
export async function createShopWithValidation(shopData) {
  // 1. 前端验证
  if (!shopData.name) {
    throw new Error('店铺名称不能为空')
  }
  if (!shopData.address) {
    throw new Error('店铺地址不能为空')
  }
  if (!shopData.phone) {
    throw new Error('联系电话不能为空')
  }
  
  // 2. 发送请求
  return await apiRequest('/api/admin/foodStore/create', {
    method: 'POST',
    body: JSON.stringify(shopData)
  }, '创建店铺')
}

// ==================== 4. 批量操作示例 ====================

/**
 * 批量删除店铺
 * @param {Array} shopIds - 店铺ID数组
 */
export async function batchDeleteShops(shopIds) {
  if (!shopIds || shopIds.length === 0) {
    throw new Error('请选择要删除的店铺')
  }
  
  try {
    // 显示进度提示
    ElNotification({
      title: '批量删除',
      message: `正在删除 ${shopIds.length} 个店铺...`,
      type: 'info',
      duration: 0 // 不自动关闭
    })
    
    const result = await apiRequest('/api/admin/foodStore/batchDelete', {
      method: 'DELETE',
      body: JSON.stringify({ ids: shopIds })
    }, '批量删除店铺')
    
    // 关闭进度提示，显示成功消息
    ElNotification.closeAll()
    ElNotification({
      title: '删除成功',
      message: `成功删除 ${shopIds.length} 个店铺`,
      type: 'success'
    })
    
    return result
  } catch (error) {
    ElNotification.closeAll()
    throw error
  }
}

// ==================== 5. 文件上传示例 ====================

/**
 * 上传店铺图片
 * @param {File} file - 图片文件
 * @param {Function} onProgress - 进度回调
 */
export async function uploadShopImage(file, onProgress) {
  try {
    // 1. 文件验证
    if (!file) {
      throw new Error('请选择要上传的文件')
    }
    
    const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
    if (!allowedTypes.includes(file.type)) {
      throw new Error('只支持 JPG、PNG、GIF 格式的图片')
    }
    
    const maxSize = 5 * 1024 * 1024 // 5MB
    if (file.size > maxSize) {
      throw new Error('图片大小不能超过 5MB')
    }
    
    // 2. 创建 FormData
    const formData = new FormData()
    formData.append('file', file)
    formData.append('type', 'shop_image')
    
    // 3. 发送请求（带进度监听）
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()
      
      // 监听上传进度
      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable) {
          const progress = Math.round((event.loaded / event.total) * 100)
          onProgress && onProgress(progress)
        }
      })
      
      // 监听响应
      xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
          try {
            const result = JSON.parse(xhr.responseText)
            if (result.code === 200) {
              resolve(result.data)
            } else {
              reject(new Error(result.msg || '上传失败'))
            }
          } catch (error) {
            reject(new Error('响应解析失败'))
          }
        } else {
          reject(new Error(`HTTP error! status: ${xhr.status}`))
        }
      })
      
      // 监听错误
      xhr.addEventListener('error', () => {
        reject(new Error('网络错误'))
      })
      
      // 发送请求
      xhr.open('POST', '/api/admin/foodStore/upload')
      
      // 添加认证头
      const token = localStorage.getItem('admin_token')
      if (token) {
        xhr.setRequestHeader('Authorization', `Bearer ${token}`)
      }
      
      xhr.send(formData)
    })
  } catch (error) {
    handleApiError(error, '上传图片')
    throw error
  }
}

// ==================== 6. 缓存机制示例 ====================

// 简单的内存缓存
const cache = new Map()

/**
 * 带缓存的获取店铺详情
 * @param {number} shopId - 店铺ID
 * @param {boolean} forceRefresh - 是否强制刷新
 */
export async function getShopDetailWithCache(shopId, forceRefresh = false) {
  const cacheKey = `shop_detail_${shopId}`
  
  // 检查缓存
  if (!forceRefresh && cache.has(cacheKey)) {
    const cached = cache.get(cacheKey)
    const now = Date.now()
    
    // 缓存有效期 5 分钟
    if (now - cached.timestamp < 5 * 60 * 1000) {
      console.log('使用缓存数据:', cached.data)
      return cached.data
    }
  }
  
  // 获取新数据
  try {
    const data = await apiRequest(`/api/admin/foodStore/details/${shopId}`, {}, '获取店铺详情')
    
    // 存入缓存
    cache.set(cacheKey, {
      data,
      timestamp: Date.now()
    })
    
    return data
  } catch (error) {
    // 如果请求失败且有缓存，返回缓存数据
    if (cache.has(cacheKey)) {
      console.log('请求失败，使用缓存数据')
      return cache.get(cacheKey).data
    }
    throw error
  }
}

/**
 * 清除缓存
 * @param {string} pattern - 缓存键模式
 */
export function clearCache(pattern) {
  if (pattern) {
    // 清除匹配的缓存
    for (const key of cache.keys()) {
      if (key.includes(pattern)) {
        cache.delete(key)
      }
    }
  } else {
    // 清除所有缓存
    cache.clear()
  }
}

// ==================== 7. 重试机制示例 ====================

/**
 * 带重试的 API 请求
 * @param {Function} apiFunction - API 函数
 * @param {Array} args - 函数参数
 * @param {number} maxRetries - 最大重试次数
 * @param {number} delay - 重试延迟（毫秒）
 */
export async function apiWithRetry(apiFunction, args = [], maxRetries = 3, delay = 1000) {
  let lastError
  
  for (let i = 0; i <= maxRetries; i++) {
    try {
      return await apiFunction(...args)
    } catch (error) {
      lastError = error
      
      // 如果是最后一次尝试，直接抛出错误
      if (i === maxRetries) {
        break
      }
      
      // 如果是客户端错误（4xx），不重试
      if (error.message.includes('HTTP error') && error.message.includes('4')) {
        break
      }
      
      console.log(`第 ${i + 1} 次请求失败，${delay}ms 后重试...`)
      
      // 等待后重试
      await new Promise(resolve => setTimeout(resolve, delay))
      
      // 指数退避：每次重试延迟翻倍
      delay *= 2
    }
  }
  
  throw lastError
}

// 使用示例：
// const result = await apiWithRetry(getShopListWithErrorHandling, [params])